package net.jiastudy.biz.project.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import net.jiastudy.biz.project.entity.DeptProject;
import net.jiastudy.biz.project.entity.DeptProjectMember;
import net.jiastudy.biz.project.entity.DeptProjectMoney;
import net.jiastudy.biz.project.entity.DeptProjectWork;
import net.jiastudy.biz.project.entity.MoneyImporter;
import net.jiastudy.biz.project.entity.ProjectImporter;
import net.jiastudy.biz.project.mapper.DeptProjectMapper;
import net.jiastudy.biz.project.mapper.DeptProjectMemberMapper;
import net.jiastudy.biz.project.mapper.DeptProjectMoneyMapper;
import net.jiastudy.biz.project.mapper.DeptProjectWorkMapper;
import net.jiastudy.biz.project.service.DeptProjectReportService;
import net.jiastudy.biz.project.service.DeptProjectService;
import net.jiastudy.biz.sys.entity.Dept;
import net.jiastudy.biz.sys.service.DeptService;
import net.jiastudy.biz.user.entity.User;
import net.jiastudy.biz.user.service.UserService;
import net.jiastudy.core.base.BaseService;
import net.jiastudy.core.exception.ServiceException;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
@Transactional(rollbackFor = Exception.class)
public class DeptProjectServiceImpl extends BaseService<DeptProjectMapper, DeptProject> implements DeptProjectService  {

	@Resource
	private DeptProjectMemberMapper memberMapper;
	
	@Resource
	private DeptProjectMoneyMapper moneyMapper;
	
	@Resource
	private DeptProjectWorkMapper workMapper;
	
	@Resource
	private DeptProjectReportService reportService;

	@Resource
	private DeptService deptService;

	@Resource
	private UserService userService;

	@Override
	public DeptProject createProject(DeptProject project) {
		if (this.insert(project)) {
			if (null != project.getMembers() && !project.getMembers().isEmpty()) {
				for (DeptProjectMember member : project.getMembers()) {
					member.setProjectId(project.getId());
					this.createMember(member);
				}
			}
			if (null != project.getWorks() && !project.getWorks().isEmpty()) {
				for (DeptProjectWork work : project.getWorks()) {
					work.setProjectId(project.getId());
					if (null == work.getSource()) {
						work.setSource("B");
					}
					this.createWork(work);
				}
			}
			if (null != project.getMoney() && !project.getMoney().isEmpty()) {
				for (DeptProjectMoney money : project.getMoney()) {
					money.setProjectId(project.getId());
					this.createMoney(money);
				}
			}
			return project;
		} else {
			return null;
		}
	}

	@Override
	public Boolean deleteProject(Long id) {
		DeptProject deptProject = getById(id);

		if (null != deptProject) {
			this.deleteById(id);
			reportService.deleteReportByProjectId(id);
		}

		return true;
	}

	public DeptProjectMember createMember(DeptProjectMember member) {
		memberMapper.insert(member);
		return member;
	}
	
	public DeptProjectMoney createMoney(DeptProjectMoney money) {
		moneyMapper.insert(money);
		return money;
	}
	
	public DeptProjectWork createWork(DeptProjectWork work) {
		workMapper.insert(work);
		return work;
	}

	@Override
	public Page<DeptProject> pageDeptProjects(Page<DeptProject> page, Map<String, String> conditions, Sort sort) {
		Wrapper<DeptProject> wrapper = new EntityWrapper<>();
		if (conditions.containsKey("keywords") && StrUtil.isNotEmpty(conditions.get("keywords"))) {
			String keywords = conditions.get("keywords");
			wrapper.andNew().like("name", keywords);
		}
		this.generateSort(wrapper, sort);
		page = this.selectPage(page, wrapper);
		List<DeptProject> projects = page.getRecords();
		for (DeptProject project : projects) {
			project.setMembers(this.findMembersByProjectId(project.getId()));
			project.setMoney(this.findMoneyByProjectId(project.getId()));
			project.setWorks(this.findWorksByProjectId(project.getId()));
			project.setReports(reportService.findReportsByProjectId(project.getId()));
		}
		return page;
	}

	public List<DeptProjectMember> findMembersByProjectId(Long id) {
		Wrapper<DeptProjectMember> wrapper = new EntityWrapper<>();
		wrapper.eq("project_id", id);
		wrapper.orderBy("seq", true);
        return memberMapper.selectList(wrapper);
	}
	
	public List<DeptProjectMoney> findMoneyByProjectId(Long id) {
		Wrapper<DeptProjectMoney> wrapper = new EntityWrapper<>();
		wrapper.eq("project_id", id);
		wrapper.orderBy("seq", true);
        return moneyMapper.selectList(wrapper);
	}
	
	public List<DeptProjectWork> findWorksByProjectId(Long id) {
		Wrapper<DeptProjectWork> wrapper = new EntityWrapper<>();
		wrapper.eq("project_id", id);
		wrapper.orderBy("seq", true);
		List<DeptProjectWork> works = workMapper.selectList(wrapper);
		for (DeptProjectWork work: works) {
			if (work.getUserIds() != null && !work.getUserIds().equals("[]")) {
				Set<Long> userIds = new HashSet<>();
				String[] strUserIds = work.getUserIds().split(",");
				for (String userId: strUserIds) {
					userIds.add(Long.parseLong(userId));
				}
				work.setUsers(userService.findUsersByIds(userIds));
			} else {
				work.setUserIds(null);
			}
		}
        return works;
	}

	@Override
	public DeptProject updateProject(DeptProject project) {
		if (this.updateById(project)) {
			return project;
		}
		return null;
	}

	@Override
	public DeptProjectMember updateMember(DeptProjectMember member) {
		memberMapper.updateById(member);
		return member;
	}

	@Override
	public boolean deleteMemeber(Long memberId) {
		memberMapper.deleteById(memberId);

		return true;
	}

	@Override
	public boolean deleteMoney(Long moneyId) {
		moneyMapper.deleteById(moneyId);

		return true;
	}

	@Override
	public DeptProjectMoney updateMoney(DeptProjectMoney money) {
		moneyMapper.updateById(money);
		return money;
	}

	@Override
	public DeptProjectWork updateWork(DeptProjectWork work) {
		workMapper.updateById(work);
		return work;
	}

	@Override
	public boolean deleteWork(Long workId) {
		workMapper.deleteById(workId);
		return true;
	}

	@Override
	public DeptProject getById(Long id) {
		DeptProject project = this.selectById(id);
		project.setMembers(this.findMembersByProjectId(id));
		project.setMoney(this.findMoneyByProjectId(id));
		project.setWorks(this.findWorksByProjectId(id));
		return project;
	}

	@Override
	public Map<String, List<DeptProject>> findDeptProjects(Map<String, Object> condition) {
		Wrapper<DeptProject> wrapper = new EntityWrapper<>();
		Map<String, List<DeptProject>> map = new HashMap<>();
		if (condition.containsKey("deptId")) {
			wrapper.eq("dept_id", condition.get("deptId"));
		}
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
		Date date = new Date();
		wrapper.like("create_date", sdf.format(date));
		List<DeptProject> list = selectList(wrapper);
		for (DeptProject project : list) {
			project.setMembers(this.findMembersByProjectId(project.getId()));
			project.setMoney(this.findMoneyByProjectId(project.getId()));
			project.setWorks(this.findWorksByProjectId(project.getId()));
			project.setReports(reportService.findReportsByProjectId(project.getId()));
			if (map.containsKey(project.getDept().getName())) {
				map.get(project.getDept().getName()).add(project);
			} else {
				List<DeptProject> myProjects = new ArrayList<>();
				myProjects.add(project);
				map.put(project.getDept().getName(), myProjects);
			}
		}
		return map;
	}

	@Override
	public void importProject(List<ProjectImporter> list, List<MoneyImporter> moneyList) {
		DeptProject project = new DeptProject();
		List<DeptProjectWork> works = new ArrayList<>();
		List<DeptProjectMember> members = new ArrayList<>();
		for (ProjectImporter projectImporter : list) {
			if (projectImporter.getWorkName() == null) {
				break;
			}

			if (null != projectImporter.getProjectName()) {
				project.setName(projectImporter.getProjectName());
			}

			if (null != projectImporter.getDeptHeads()) {
				List<String> deptHeads = new ArrayList<>();
				deptHeads = Arrays.asList(projectImporter.getDeptHeads().split("、"));
				User deptHead = userService.getUserByName(deptHeads.get(0));
				if (null == deptHead) {
					throw new ServiceException(deptHeads.get(0) + "不存在");
				}

				project.setDeptHeadId(deptHead.getId());
			}

			if (null != projectImporter.getDate()) {
				project.setEndDate(projectImporter.getDate());
			}

			if (null != projectImporter.getWorkTarget()) {
				project.setWorkName(projectImporter.getWorkTarget());
			}

			if (null != projectImporter.getDeptName()) {
				Dept dept = deptService.getDeptByName(projectImporter.getDeptName());
				if (null == dept) {
					throw new ServiceException("部门" + projectImporter.getDeptName() + "不存在");
				}
				project.setDeptId(dept.getId());
			}

			DeptProjectWork deptProjectWork = new DeptProjectWork();
			deptProjectWork.setName(projectImporter.getWorkName());
			deptProjectWork.setSeq(projectImporter.getSeq());
			deptProjectWork.setStartDate(projectImporter.getStartDate());
			deptProjectWork.setEndDate(projectImporter.getEndDate());
			deptProjectWork.setSource(projectImporter.getSource());
			List<String> userNames = new ArrayList<>();
			userNames = Arrays.asList(projectImporter.getUserNames().split("、"));
			String userIds = "";
			for (String userName : userNames) {
				User user = userService.getUserByName(userName);
				if (null == user) {
					throw new ServiceException(userName + "不存在");
				}

				if (!userIds.equals("")) {
					userIds = userIds + ",";
				}

				Boolean hasSet = false;
				for (DeptProjectMember setDeptProjectMember : members) {
					if (setDeptProjectMember.getUserName().equals(userName)) {
						hasSet = true;
					}
				}
				if (!hasSet) {
					DeptProjectMember deptProjectMember = new DeptProjectMember();
					deptProjectMember.setUserId(user.getId());
					deptProjectMember.setUserName(userName);
					deptProjectMember.setSeq(members.size() + 1);
					members.add(deptProjectMember);
				}

				userIds = userIds + user.getId().toString();
			}
			deptProjectWork.setUserIds(userIds);

			works.add(deptProjectWork);
		}

		project.setWorks(works);
		User currentUser = getCurrentUser();
		project.setCreatedUserId(currentUser.getId());

		List<DeptProjectMoney> money = new ArrayList();
		int seq = 1;
		for	(MoneyImporter moneyImporter : moneyList) {
			DeptProjectMoney deptProjectMoney = new DeptProjectMoney();
			deptProjectMoney.setMoney(moneyImporter.getMoney());
			deptProjectMoney.setName(moneyImporter.getName());
			deptProjectMoney.setSeq(seq);
			seq ++;
			money.add(deptProjectMoney);
		}
		project.setMoney(money);
		project.setMembers(members);
		createProject(project);
	}
}
